package DecisionMaker;

import java.util.Vector;

public class RuleClass {
    Vector premise = new Vector();
    Vector conclusion = new Vector();
    Vector fuzzyValues;
    String rawRule;
    String updatedPremise;
    public boolean printProgress;

	public RuleClass(String rule, Vector f)
	{
        fuzzyValues = f;
        rawRule = rule;
    }

    public String solvePremise() {
        premise = new Vector();
        conclusion = new Vector();
        recognizePremise(rawRule);
        recognizeConclusion(rawRule);
        printProgress = false;

        // Het oplossen van de IS constructies
        String replacement = null;
        while (premise.elementAt(0).toString().indexOf("IS") > -1) {
            // Alle IS constructies zijn nog niet opgelost, er wordt gezocht naar de eerst volgende
            for (int x = 0; x < getWordCount(premise.elementAt(0).toString());
                         x++) {
                if (getWord(premise.elementAt(0).toString(), x).equals("IS"))
                {
                    // Gevonden, oplossen
                    replacement = "";
                    for (int counter1 = 0; counter1 < x - 1; counter1++)
                    {
                        replacement += getWord(premise.elementAt(0).toString(), counter1) + " ";
                    }
                    replacement += solveIS(getWord(premise.elementAt(0).toString(), x - 1), getWord(premise.elementAt(0).toString(), x + 1)) + " ";
                    for (int counter2 = x + 2; counter2 < getWordCount(premise.elementAt(0).toString()); counter2++)
                    {
                        replacement += getWord(premise.elementAt(0).toString(),counter2) + " ";
                    }
                    if(printProgress==true)
                    {
                        System.out.println("** IS-SOLVER: Solved To: " + replacement);
                    }
                    premise = new Vector();
                    premise.add(replacement);
                }
            }
        }
        // IS constructies opgelost. AND contstructies nu oplossen
        while (premise.elementAt(0).toString().indexOf("AND") > -1) {
			// Alle AND constructies zijn nog niet opgelost, er wordt gezocht naar de eerst volgende
            for (int x = 0; x < getWordCount(premise.elementAt(0).toString());x++)
            {
                if (getWord(premise.elementAt(0).toString(), x).equals("AND"))
                {
                    // word found, solve and replace it
                    // Build replacement for premise
                    replacement = "";
                    for (int counter1 = 0; counter1 < x - 1; counter1++)
                    {
                        replacement +=getWord(premise.elementAt(0).toString(), counter1) + " ";
                    }
                    replacement += solveAND(getWord(premise.elementAt(0).toString(), x - 1), getWord(premise.elementAt(0).toString(), x + 1)) + " ";
                    for (int counter2 = x + 2; counter2 < getWordCount(premise.elementAt(0).toString()); counter2++)
                    {
                        replacement += getWord(premise.elementAt(0).toString(), counter2) + " ";
                    }
                    premise = new Vector();
                    premise.add(replacement);

                    if(printProgress==true)
                    {
                        System.out.println("** AND-SOLVER: Solved To: " + replacement);
                    }

                }

            }
        }
        // AND constructions solved. Now going to solve OR constructions
        while (premise.elementAt(0).toString().indexOf("OR") > -1)
        {
            // there are still AND contruction in the premise
            // search for the first one we find, and solve it
            for (int x = 0; x < getWordCount(premise.elementAt(0).toString()); x++)
            {
                if (getWord(premise.elementAt(0).toString(), x).equals("OR"))
                {
					// Gevonden, oplossen
                    replacement = "";
                    for (int counter1 = 0; counter1 < x - 1; counter1++)
                    {
                        replacement +=getWord(premise.elementAt(0).toString(), counter1) + " ";
                    }
                    replacement += solveOR(getWord(premise.elementAt(0).toString(), x - 1),getWord(premise.elementAt(0).toString(), x + 1)) + " ";
                    for (int counter2 = x + 2; counter2 < getWordCount(premise.elementAt(0).toString()); counter2++)
                    {
                        replacement += getWord(premise.elementAt(0).toString(),counter2) + " ";
                    }
                    premise = new Vector();
                    premise.add(replacement);

                    if(printProgress==true)
                    {
                        System.out.println("** OR-SOLVER: Solved To: " + replacement);
                    }

                }

            }
        }

        return replacement;
    }

    private String solveIS(String arg1, String arg2)
    {
        for (int i = 0; i < fuzzyValues.size(); i++)
        {
            // get Universe name en zoek in Fuzzyvalues
            if (fuzzyValues.elementAt(i).toString().indexOf(arg1) >= 0)
            {
                // Universe begin gevonden - zoeken naar de set
                for (int c = i; c < fuzzyValues.size(); c++)
                {
                    if (fuzzyValues.elementAt(c).toString().indexOf(arg2) >= 0)
                    {
                        // set gevonden, return oplossing
                        if(printProgress==true)
                        {
                            System.out.println("** IS-SOLVER: Premise:" + premise.elementAt(0).toString().substring(0, premise.elementAt(0).toString().length() - 1));
                            System.out.println("** IS-SOLVER: Universe: \"" + arg1 + "\" Set: \"" + arg2 + "\" Value: " + fuzzyValues.elementAt(c + 1).toString());
                        }
                        return fuzzyValues.elementAt(c + 1).toString();
                    }
                }
            }
        }
        return null;
    }

    private String solveAND(String arg1, String arg2)
    {
        if (Double.parseDouble(arg1) < Double.parseDouble(arg2))
        {
            if(printProgress==true)
            {
                System.out.println("** AND-SOLVER: Premise:" + premise.elementAt(0).toString());
            }
            return arg1;
        }

        else
        {
            if(printProgress==true)
            {
                System.out.println("** AND-SOLVER: Premise:" + premise.elementAt(0).toString());
            }
            return arg2;
        }
    }

    private String solveOR(String arg1, String arg2)
    {
        if (Double.parseDouble(arg1) > Double.parseDouble(arg2))
        {
            if(printProgress==true)
            {
                System.out.println("** OR-SOLVER: Premise:" + premise.elementAt(0).toString());
            }
            return arg1;
        }
        else
        {
            if(printProgress==true)
            {
                System.out.println("** OR-SOLVER: Premise:" + premise.elementAt(0).toString());
            }
            return arg2;
        }
    }

    private void recognizePremise(String rule)
    {
        premise.add(rule.substring((rule.indexOf("IF") + 2),(rule.indexOf("THEN"))));
        if(printProgress==true)
        {
            System.out.println("\n** PREMISE-RECOGNITION: Premise is: " + premise.elementAt(0).toString().substring(0,premise.elementAt(0).toString().length()-1));
        }
    }

    private void recognizeConclusion(String rule)
    {
        // raw conclusion @ conclusion(0)
        conclusion.add(rule.substring((rule.indexOf("THEN") + 4)));
        if(printProgress==true)
        {
            System.out.println("** CONCLUSION-RECOGNITION: Conclusion is: " + conclusion.elementAt(0).toString().substring(0,conclusion.elementAt(0).toString().length()-1));
        }
    }

    public Vector solveConclusion()
    {
        Vector fuzzyValues = new Vector();
        // "oplossen" IS statements
        while (conclusion.elementAt(0).toString().indexOf("IS") >= 0)
        {
            for (int x = 0; x < getWordCount(conclusion.elementAt(0).toString()); x++)
            {
                if (getWord(conclusion.elementAt(0).toString(), x).indexOf("IS") >=0)
                {
                    // IS word gevonden
                    // save Universe name
                    fuzzyValues.add(getWord(conclusion.elementAt(0).toString(), x - 1));
                    // save Fuzzyset
                    fuzzyValues.add(getWord(conclusion.elementAt(0).toString(), x + 1));
                    // delete statement uit de vector
                    String newConclusion = "";

                    for (int count1 = (x + 2);count1 < getWordCount(fuzzyValues.elementAt(0).toString()); count1++)
                    {
                        newConclusion += getWord(conclusion.elementAt(0).toString(), count1) + " ";
                    }
                    // Volgende regel, alleen als er geprint wordt
                    String oldConclusion = conclusion.elementAt(0).toString();
                    conclusion = new Vector();
                    conclusion.add(newConclusion);
                    if(printProgress)
                    {
						System.out.println("** CONCLUSIE-OPLOSSER: Conclusie: " + oldConclusion + "** CONCLUSIE-OPLOSSER:  Opgelost naar: " + getWord(oldConclusion, 2));
                    }
                }
            }
        }
        return fuzzyValues;
    }

    private String getWord(String setstr, int nr)
    {
        int currentWord = 0;
        int i = 0;

		//spaties vervangen voor een [ of een ]
        setstr = setstr.replace('[', ' ');
        setstr = setstr.replace(']', ' ');
        setstr = setstr.trim();

        while (setstr.length() > 0)
        {
            if (i == setstr.length() || setstr.charAt(i) == '\n' || setstr.charAt(i) == ' ' || setstr.charAt(i) == '\t') {
                //einde van huidige woord gevonden
                if (nr == currentWord)
                {
                        //huidige woord moet worden teruggegeven
                        return (setstr.substring(0, i)).trim();
                }
                //nog niet het goede woord, doorgaan met volgende woord zoeken
                setstr = (setstr.substring(i, setstr.length())).trim();
                i = 0;
                currentWord++;
            }
            i++;
        }
        return null;
    }

    private int getWordCount(String setstr)
    {
        int currentWord = 0;
        int i = 0;

        //spaties verwijderen (einde en begin)

        setstr = setstr.trim();

        while (setstr.length() > 0)
        {
            if (i == setstr.length() || setstr.charAt(i) == '\n' || setstr.charAt(i) == ' ' || setstr.charAt(i) == '\t')
            {
                //einde van huidige woord gevonden
                setstr = (setstr.substring(i, setstr.length())).trim();
                i = 0;
                currentWord++;
            }
            i++;
        }
        return currentWord;
    }
}
